package com.uyuni.rpc.client.provider.flow.control;

import com.uyuni.rpc.common.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


/**
 * @author BazingaLyn
 * @description 限制每个服务单位时间(分钟)的调用次数
 * @time 2016年9月9日
 * @modifytime
 */
public class ServiceFlowControllerManager {

    private static final Logger logger = LoggerFactory.getLogger(ServiceFlowControllerManager.class);

    //服务限流器map 一个服务对应一个限流器
    private static final ConcurrentMap<String/*服务名*/, Pair<Long/*限流次数*/, ServiceFlowController/*限流器*/>> globalFlowControllerMap = new ConcurrentHashMap<>();

    /**
     * 设置某个服务的单位时间的最大调用次数
     *
     * @param serviceName  服务名
     * @param maxCallCount 最大调用次数
     */
    public void setServiceLimitVal(String serviceName, Long maxCallCount) {
        Pair<Long, ServiceFlowController> pair = new Pair<>();
        pair.setKey(maxCallCount);
        pair.setValue(new ServiceFlowController());
        globalFlowControllerMap.put(serviceName, pair);
    }

    /**
     * 原子增加某个服务的调用次数
     *
     * @param serviceName
     */
    public void incrementCallCount(String serviceName) {
        Pair<Long, ServiceFlowController> pair = globalFlowControllerMap.get(serviceName);
        if (null == pair) {
            logger.warn("serviceName [{}] matched no flowController", serviceName);
            return;
        }
        ServiceFlowController serviceFlowController = pair.getValue();
        serviceFlowController.incrementOfCurrentMinute();

    }

    /**
     * 查看某个服务是否可用
     *
     * @param serviceName
     * @return
     */
    public boolean isAllow(String serviceName) {
        Pair<Long, ServiceFlowController> pair = globalFlowControllerMap.get(serviceName);
        if (null == pair) {
            logger.warn("serviceName [{}] matched no flowController", serviceName);
            return false;
        }
        ServiceFlowController serviceFlowController = pair.getValue();
        Long maxCallCount = pair.getKey();
        long hasCallCount = serviceFlowController.getCallCountOfCurrentMinute();
        return hasCallCount <= maxCallCount;

    }

    /**
     * 获取到某个服务的上一分钟的调用次数
     *
     * @param serviceName
     * @return
     */
    public Long getCallCountOfLastMinute(String serviceName) {
        Pair<Long, ServiceFlowController> pair = globalFlowControllerMap.get(serviceName);

        if (null == pair) {
            logger.warn("serviceName [{}] matched no flowController", serviceName);
            return 0L;
        }
        ServiceFlowController serviceFlowController = pair.getValue();
        return serviceFlowController.getCallCountOfLastMinute();
    }

    /**
     * 将下一秒的调用次数置为0
     */
    public void clearAllServiceNextMinuteCallCount() {

        for (String service : globalFlowControllerMap.keySet()) {

            Pair<Long, ServiceFlowController> pair = globalFlowControllerMap.get(service);
            if (null == pair) {
                logger.warn("serviceName [{}] matched no flowController", service);
                continue;
            }
            ServiceFlowController serviceFlowController = pair.getValue();
            serviceFlowController.clearNextMinuteCallCount();
        }
    }


}
